from Lexer import Lexer
import ply.yacc as yacc
import ErrorSintactico
import ASTVisitor
import NodosArbol
import VarGlobales
import prueba
import sys

sys.setrecursionlimit(4000)


###################### ANALISIS SINTACTICO ##########################

class parser(object):
    
    def __init__(self, tokens):
        self.tokens = tokens
        self.yacc = yacc.yacc(module = self)
        
        
    def parse(self, text):
        return self.yacc.parse(text)
    
    def p_programa1(self, p):
        """PROGRAMA : LISTAPROCEDIMIENTOS"""
        p[0] = NodosArbol.Programa(p[1])
        
    def p_listaprocedimientos1(self, p):
        """LISTAPROCEDIMIENTOS : LISTAPROCEDIMIENTOS PROCEDIMIENTOS"""
        p[1].add(p[2])
        p[0] = p[1]
        
    def p_listaprocedimientos2(self, p):
        """LISTAPROCEDIMIENTOS : empty"""
        p[0] = NodosArbol.ListaFunciones()
    
    def p_procedimientos1(self, p):
        """PROCEDIMIENTOS : procedimiento ID '(' LISTAARGUMENTOS ')' BLOQUE"""
        p[0] = NodosArbol.procedimiento(NodosArbol.Id(p[2],p.lineno(2)), p[4], p[6])
        
    def p_procedimientos2(self, p):
        """PROCEDIMIENTOS : procedimiento ID '(' ')' BLOQUE"""
        p[0] = NodosArbol.procedimiento(NodosArbol.Id(p[2],p.lineno(2)), None, p[5])
        
    def p_procedimientos3(self, p):
        """PROCEDIMIENTOS : pr ID '(' LISTAARGUMENTOS ')' BLOQUE"""
        p[0] = NodosArbol.procedimiento(NodosArbol.Id(p[2],p.lineno(2)), p[4], p[6])
        
    def p_procedimientos4(self, p):
        """PROCEDIMIENTOS : pr ID '(' ')' BLOQUE"""
        p[0] = NodosArbol.procedimiento(NodosArbol.Id(p[2],p.lineno(2)), None, p[5])
        
    def p_listaargumentos1(self, p):
        """LISTAARGUMENTOS : LISTAARGUMENTOS ',' ID"""
        p[1].add(NodosArbol.Id(p[3],p.lineno(3)))
        p[0] = p[1]
    
    def p_listaargumentos2(self, p):
        """LISTAARGUMENTOS : ID"""
        p[0] = NodosArbol.ListaArgumentos(NodosArbol.Id(p[1], p.lineno(1)))
        
    def p_bloque(self, p):
        """BLOQUE : inicio LISTAINSTRUCCIONES fin"""
        p[0] = NodosArbol.bloque(p[2])
        
    def p_listainstrucciones1(self, p):
        """LISTAINSTRUCCIONES : LISTAINSTRUCCIONES INSTRUCCION"""
        p[1].add(p[2])
        p[0] = p[1]
    
    def p_listainstrucciones2(self, p):
        """LISTAINSTRUCCIONES : empty"""
        p[0] = NodosArbol.ListaInstruciones()
        
    #PROBLEMAS
    def p_instruccion1(self, p):
        """INSTRUCCION : INSTRUCCIONNORMAL BOOLEANO1"""
        p[0] = NodosArbol.InstruccionNormal(p[1], p[2], p.lineno(1))
        
    def p_instruccion2(self, p):
        """INSTRUCCION : INSTRUCCIONSIMPLE"""
        p[0] = NodosArbol.InstruccionSimple(p[1])
    
    def p_instruccion3(self, p):
        """INSTRUCCION : LLAMADA"""
        p[0] = p[1]
        
    def p_instruccion4(self, p):
        """INSTRUCCION : BIFURCACION"""
        p[0] = p[1]
        
    def p_instruccion5(self, p):
        """INSTRUCCION : CICLOREPETIR"""
        p[0] = p[1]
        
    def p_instruccion6(self, p):
        """INSTRUCCION : CICLOPARA"""
        p[0] = p[1]
        
    def p_instruccion7(self, p):
        """INSTRUCCION : CICLOMIENTRAS"""
        p[0] = p[1]
        
    def p_instruccion8(self, p):
        """INSTRUCCION : ASIGNACION"""
        p[0] = p[1]
    
    def p_instruccion9(self, p):
        """INSTRUCCION : retorno BOOLEANO1"""
        p[0] = NodosArbol.Retorno(p[2])
        
    def p_asignacion(self, p):
        """ASIGNACION : ID '=' BOOLEANO1"""
        p[0] = NodosArbol.Asignacion(NodosArbol.Id(p[1], p.lineno(1)), p[3])
        
    def p_llamada1(self, p):
        """LLAMADA : ID '(' LISTAPARAMETROS ')'"""
        p[0] = NodosArbol.LLamada(NodosArbol.Id(p[1], p.lineno(1)),p[3],p.lineno(1))
        
    def p_llamada2(self, p):
        """LLAMADA : ID '(' ')'"""
        p[0] = NodosArbol.LLamada(NodosArbol.Id(p[1], p.lineno(1)),None,p.lineno(1))
        
    def p_listaparametros1(self, p):
        """LISTAPARAMETROS : LISTAPARAMETROS ',' BOOLEANO1"""
        p[1].add(p[3])
        p[0] = p[1]
        
    def p_listaparametros2(self,p):
        """LISTAPARAMETROS : BOOLEANO1"""
        p[0] = NodosArbol.ListaParametros(p[1]) 
            
    def p_ciclorepetir1(self, p):
        """CICLOREPETIR : repetir EXPRESION BLOQUE"""
        p[0] = NodosArbol.CicloRepetir(p[2], p[3], p.lineno(1))
    
    #PROBLEMAS    
    def p_ciclopara(self,p):
        """CICLOPARA : para ID '=' EXPRESION hasta EXPRESION ',' incremento '=' EXPRESION BLOQUE"""
        p[0] = NodosArbol.CicloPara(NodosArbol.Id(p[2],p.lineno(2)), p[4], p[6], p[10], p[11], p.lineno(3))
   
    def p_ciclomientras(self, p):
        """CICLOMIENTRAS : mientras BOOLEANO1 BLOQUE"""
        p[0] = NodosArbol.InstruccionMientras(p[2], p[3], p.lineno(1))
    
    def p_bifurcacion(self, p):
        """BIFURCACION : si BOOLEANO1 BLOQUE ELSE"""
        p[4].linea = p.lineno(2)
        p[4].condicion = p[2]
        p[4].bloque1 = p[3]
        p[0] = p[4]
    
    def p_else1(self, p):
        """ELSE : sino BLOQUE"""
        p[0] = NodosArbol.InstruccionSI(None, None, p[2])
        
    def p_else2(self, p):
        """ELSE : empty"""
        p[0] = NodosArbol.InstruccionSI()
        
    def p_instruccionnormal1(self, p):
        """INSTRUCCIONNORMAL : avanzar"""
        p[0] = p[1]
        
    def p_instruccionnormal2(self, p):
        """INSTRUCCIONNORMAL : av"""
        p[0] = p[1]
        
    def p_instruccionnormal3(self, p):
        """INSTRUCCIONNORMAL : retroceder"""
        p[0] = p[1]
        
    def p_instruccionnormal4(self, p):
        """INSTRUCCIONNORMAL : rt"""
        p[0] = p[1]
        
    def p_instruccionnormal5(self, p):
        """INSTRUCCIONNORMAL : girarizquierda"""
        p[0] = p[1]
        
    def p_instruccionnormal6(self, p):
        """INSTRUCCIONNORMAL : gi"""
        p[0] = p[1]
        
    def p_instruccionnormal7(self, p):
        """INSTRUCCIONNORMAL : girarderecha"""
        p[0] = p[1]
        
    def p_instruccionnormal8(self, p):
        """INSTRUCCIONNORMAL : gd"""
        p[0] = p[1]
    
    def p_instruccionnormal9(self, p):
        """INSTRUCCIONNORMAL : escribe"""
        p[0] = p[1]
    
    def p_instruccionsimple1(self, p):
        """INSTRUCCIONSIMPLE : alto"""
        p[0] = p[1]
           
    def p_instruccionsimple2(self, p):
        """INSTRUCCIONSIMPLE : al"""
        p[0] = p[1]
    
    def p_instruccionsimple3(self, p):
        """INSTRUCCIONSIMPLE : bajarpluma"""
        p[0] = p[1]
        
    def p_instruccionsimple4(self, p):
        """INSTRUCCIONSIMPLE : bp"""
        p[0] = p[1]
        
    def p_instruccionsimple5(self, p):
        """INSTRUCCIONSIMPLE : subirpluma"""
        p[0] = p[1]
        
    def p_instruccionsimple6(self, p):
        """INSTRUCCIONSIMPLE : sp"""
        p[0] = p[1]
        
    def p_instruccionsimple7(self, p):
        """INSTRUCCIONSIMPLE : borrarpantalla"""
        p[0] = p[1]
        
    def p_instruccionsimple8(self, p):
        """INSTRUCCIONSIMPLE : bo"""
        p[0] = p[1]
        
    def p_booleano1(self, p):
        """BOOLEANO1 : BOOLEANO1 o BOOLEANO2 """
        p[0] = NodosArbol.OpBinaria(p[2],p[1],p[3],p.lineno(2))
    
    def p_booleano2(self, p):
        """BOOLEANO1 : BOOLEANO2 """
        p[0] = p[1]
        
    def p_booleano3(self, p):
        """BOOLEANO2 : BOOLEANO2 y CONDICIONAL1 """
        p[0] = NodosArbol.OpBinaria(p[2],p[1],p[3],p.lineno(2))  
    
    def p_booleano4(self, p):
        """BOOLEANO2 : CONDICIONAL1 """
        p[0] = p[1]
        
    def p_factor11(self, p):
        """CONDICIONAL1 : CONDICIONAL1 IGUAL CONDICIONAL2 """
        p[0] = NodosArbol.OpBinaria(p[2],p[1],p[3],p.lineno(2))
        
    def p_factor12(self, p):
        """CONDICIONAL1 : CONDICIONAL1 DIFERENTE CONDICIONAL2 """
        p[0] = NodosArbol.OpBinaria(p[2],p[1],p[3],p.lineno(2))
    
    def p_factor14(self, p):
        """CONDICIONAL1 : CONDICIONAL2 """
        p[0] = p[1]
        
    def p_factor21(self, p):
        """CONDICIONAL2 : CONDICIONAL2 '<' EXPRESION """
        p[0] = NodosArbol.OpBinaria(p[2],p[1],p[3],p.lineno(2))
        
    def p_factor22(self, p):
        """CONDICIONAL2 : CONDICIONAL2 MENOROIGUAL EXPRESION """
        p[0] = NodosArbol.OpBinaria(p[2],p[1],p[3],p.lineno(2))
    
    def p_factor23(self, p):
        """CONDICIONAL2 : CONDICIONAL2 '>' EXPRESION """
        p[0] = NodosArbol.OpBinaria(p[2],p[1],p[3],p.lineno(2))
        
    def p_factor24(self, p):
        """CONDICIONAL2 : CONDICIONAL2 MAYOROIGUAL EXPRESION """ 
        p[0] = NodosArbol.OpBinaria(p[2],p[1],p[3],p.lineno(2))
        
    def p_factor26(self, p):
        """CONDICIONAL2 : EXPRESION"""
        p[0] = p[1]
        
    def p_expresion1(self, p):
        """EXPRESION : EXPRESION '+' TERMINO"""
        p[0] = NodosArbol.OpBinaria(p[2], p[1], p[3],p.lineno(2))
        
    def p_expresion2(self, p):
        """EXPRESION : EXPRESION '-' TERMINO"""
        p[0] = NodosArbol.OpBinaria(p[2], p[1], p[3], p.lineno(2))
        
    def p_expresion3(self, p):
        """EXPRESION : TERMINO"""
        p[0] = p[1]
        
    def p_termino1(self, p):
        """TERMINO : TERMINO '*' FACTOR"""
        p[0] = NodosArbol.OpBinaria(p[2], p[1], p[3], p.lineno(2))
        
    def p_termino2(self, p):
        """TERMINO : TERMINO '/' FACTOR"""
        p[0] = NodosArbol.OpBinaria(p[2], p[1], p[3], p.lineno(2))
        
    def p_termino3(self, p):
        """TERMINO : FACTOR"""
        p[0] = p[1]
        
    def p_factor1(self, p):
        """FACTOR : '(' BOOLEANO1 ')'"""  
        p[0] = NodosArbol.OpUnaria(p[1]+p[3], p[2], p.lineno(1) )         
    
    def p_factor2(self, p):
        """FACTOR : '-' FACTOR"""   
        p[0] = NodosArbol.OpUnaria(p[1], p[2], p.lineno(1))
    
    def p_factor3(self, p):
        """FACTOR : NUMEROENTERO""" 
        p[0] = NodosArbol.numeroEntero(p[1])
    
    def p_factor4(self, p):
        """FACTOR : NUMEROFLOTANTE""" 
        p[0] = NodosArbol.numeroFlotante(p[1])
        
    def p_factor5(self, p):
        """FACTOR : '!' FACTOR """ 
        p[0] = NodosArbol.OpUnaria(p[1],p[2], p.lineno(1))
    
    def p_factor6(self, p):
        """FACTOR : ID""" 
        p[0] = NodosArbol.Id(p[1],p.lineno(1))
        
    def p_factor7(self, p):
        """FACTOR : verdadero""" 
        p[0] = NodosArbol.Booleano(p[1])
        
    def p_factor8(self, p):
        """FACTOR : falso""" 
        p[0] = NodosArbol.Booleano(p[1])
        
    def p_factor9(self, p):
        """FACTOR : LLAMADA""" 
        p[0] = p[1]
        
    def p_empty(self, p):
        'empty : '
        pass
        
    def p_error(self,p):
        if p != None:
            aux = "Linea %d: Error de sintaxis" %(0 if int(p.lineno) - VarGlobales.Lresta < 0 else int(p.lineno) - VarGlobales.Lresta)
        else:
            aux = "Ultima linea: Error de sintaxis"
        raise ErrorSintactico.ErrorSintactico(aux)
    



#
#file = open("programa.in","r")
#flujo=file.read() 
####
####
####
##import time
##
#l=Lexer()
#p=parser(l.tokens)
#ast=p.parse(flujo)
#VarGlobales.PilaVariables=NodosArbol.Pila()
##ast.ejecutar('fac',None)
#tiempo_final = time.clock()
#print "%f" % (tiempo_final - tiempo_inicial)
#print VarGlobales.nlineas
##
#time.sleep(4)
#print VarGlobales.PilaVariables.imprimirVars()
#v = ASTVisitor.ASTGenCode()
#v.visit(ast)
#v.TraducirEtiquetas()
#print v.CodeIn
#vp = ASTVisitor.ASTPrint()
#vp.visit(ast)
#print vp.arbol
#
#prueba.Ejecutar(v.CodeIn.splitlines())


    
